<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="../rurple.css" type="text/css" />

<title>Erfinde das Rad nicht neu - importiere es!</title>
</head>
<body>
<h2 class="section">39. Erfinde das Rad nicht neu - importiere es!</h2>

<p>Erinnere dich an die Regel über das Vermeiden von Wiederholungen:</p>

<dl>
<dt><b>Regel # 3 </b></dt><dd>Wiederhole dich nicht beim Schreiben von
Programmen.<br/>Ich wiederhole: <b>wiederhole dich nicht!</b></dd> 
</dl>

<p>In dieser Lektion werden wir lernen, wie man es vermeidet, "das Rad neu zu
erfinden".</p>

<h3 class="section">1. Denk dran: drei mal links ergibt rechts</h3>

<p>
Weißt du noch, wie wir die Anweisung <tt>turn_right()</tt> definierten:</p>

<pre>
<span class="keyword">def</span> turn_right():
    turn_left()
    turn_left()
    turn_left()
</pre>

<p>Dies taten wir, um nicht ständig dreimal hintereinander <tt>turn_left()</tt>
tippen, wenn wir Reeborg anweisen wollten, sich nach rechts zu drehen.
Allerdings gibt es immer noch eine Menge Wiederholung, denn fast jedes Mal, wenn
wir ein neues Programm schreiben, müssen wir <tt>turn_right()</tt> wieder
definieren. Das können wir uns aber ersparen. Schreibe das folgende Programm
und versuche es zu starten.</p>

<pre>
<span class="keyword">from</span> toolbox <span class="keyword">import</span> turn_right

turn_right()
turn_off()
</pre>

<h3 class="section">2. Über <i>toolbox</i></h3>

<p>
Ich habe für dich ein Pseudo-<i>Modul</i> namens "toolbox" angelegt, das einige
Definitionen neuer Anweisungen enthält. Statt zu erklären, was jede einzelne 
Anweisung tut, zeige ich dir ein Beispielprogramm mit dem dazugehörigen Kopie
der Bildschirmausgabe.</p>

<pre>
<span class="keyword">from</span> toolbox <span class="keyword">import</span> *

turn_left()
move()
set_trace_style(1, <span class="string">'red'</span>)
turn_right()
set_trace_style(2, <span class="string">'blue'</span>)
move()
set_trace_style(1, <span class="string">'green'</span>)
climb_up_east()
set_trace_style(2, <span class="string">'blue'</span>)
move()
set_trace_style(1, <span class="string">'orange'</span>)
turn_around()
set_trace_style(2, <span class="string">'sea green'</span>)
climb_up_west()
set_trace_style(1, <span class="string">'red'</span>)
turn_around()
set_trace_style(0, <span class="string">'blue'</span>) <span class="comment"># 0 = invisible</span>
repeat(move, 4)
set_trace_style(1, <span class="string">'green'</span>)
climb_down_east()
set_trace_style(2, <span class="string">'blue'</span>)
move()
set_trace_style(1, <span class="string">'black'</span>)
turn_around()
set_trace_style(2, <span class="string">'red'</span>)
climb_down_west()
turn_off()
</pre>

<p><img alt="import"  src="../../images/inter/import.png" /></p>

<p>Statt jede neue Anweisung einzeln zu importieren, wie wir das im ersten 
Beispiel mit <tt>turn_right()</tt> getan haben, haben wir die "*"-Schreibweise
verwendet, mit der wir alle Symbole des Moduls auf einmal importieren können.
Bevor ich fortfahre, sollte ich wahrscheinlich einiges kommentieren:</p>

<ol>
<li>
Für alle, die Python-<i>Module</i> schon kennen: "toolbox" ist kein echtes Modul,
sondern ein Pseudo-Modul, dass nur in Reeborgs Welt funktioniert. Du kannst aus
Sicherheitsgründen keine "echten" Module importieren und sie in RUR-Programmen
verwenden.
</li>
<li>
Eine neue Anweisung <tt>set_trace_style()</tt> wurde benutzt. Ich hätte sie auch
<tt>set_leaking_oil_colour_and_quantity()</tt> nennen können, was in Reeborgs Welt
sinnvoller gewesen wäre ... aber nicht im allgemeinen Programmierjargon. Grob 
gesprochen ist eine Programm<i>spur</i> eine Methode, die Ausführung der Anweisungen
zu verfolgen. Normalerweise solltest du diese Anweisung nicht brauchen ... aber sie
kann von Nutzen sein, um Bugs aufzuspüren oder in Beispielen wie dem von mir
benutzten.
</li>
<li>
<span class="keyword">from</span> und <span class="keyword">import</span>
sind zwei Schlüsselwörter, wie man an der Farbe sehen kann.
</li>
<li>
Trotz ihrer Namen können einige der Anweisungen, die im Modul "toolbox" definiert 
werden, unerwartete Ergebnisse liefern, wenn der Roboter nicht die erwartete 
Anfangsorientierung hat (nicht in die erwartete Richtung blickt). Ähnliches kann 
passieren, wenn du "echte" Python-Module importierst; du musst dir der Annahmen
bewusst sein, die der richtigen Anwendung der Module zugrunde liegen. Ich werde
darauf nicht weiter eingehen; du kannst es herausfinden, indem du eigene Programme
dafür schreibst.
</li>
<li>
Meistens kannst du den Python- oder C-Quelltext der "echten" Python-Module
lesen, wenn du dich dafür interessierst. Das kann nützlich sein, wenn die 
Dokumentation fehlt, oder um zu sehen, welchen Quelltext erfahrene Programmierer
schreiben, und davon zu lernen.
</li>
<li>
Da das Pseudo-Modul toolbox ein paar Einschränkungen hat, führen einige erlaubte
Anweisungen (zum Beispiel <span class="keyword">import</span> in einem Kommentar)
zu Fehlern, die von RUR-PLE gemeldet werden.
</li>
</ol>

<h3 class="section">3. Und wenn ich den gleichen Namen nochmal verwenden will?</h3>

<p>Angenommen, du möchtest den Namen "turn_right" für etwas andereres verwenden
als das, was in "toolbox" definiert ist. Das kannst du auf verschiedenen Wegen
erreichen:</p>

<ol>
<li>Erster Weg:<br />
<pre>
<span class="keyword">import</span> toolbox
<span class="comment"># Anwendung:</span>
toolbox.turn_right()
turn_off()
</pre>

Wenn du es so machst, musst du <tt>toolbox.</tt> vor alle Namen setzen, die in
<tt>toolbox</tt> definiert sind. <tt>toolbox.turn_right()</tt> und
<tt>turn_right()</tt> sind dann zwei verschiedene Anweisungen. Die erste ist im
Modul <tt>toolbox</tt> definiert, während die zweite von dir anderswo definiert
wurde. Durch den Namensteil <tt>toolbox.</tt> kann der Leser den Namen dahinter
leicht zuordnen und kommt nicht durcheinander. Kommen dir die "gepunkteten"
Namen bekannt vor? Wenn nicht, lies dir noch mal die Lektion über die
<a href="30-dot.htm">Punktschreibweise</a> durch. Wenn ja, dann weisst du ja,
dass wir Reeborg mit <tt>Reeborg.move()</tt> veranlassen können, sich zu
bewegen. Ist das Zufall? Nein, Reeborg und <tt>toolbox</tt> haben etwas
gemeinsam: beide sind Objekte, wobei <tt>toolbox</tt> ein Objekt der
Modul-Klasse ist.<br />
</li>
<li>
Zweiter Weg:<br />
<pre>
<span class="comment"># Folgendes ist für deutschsprachige Programmierer nützlich:</span>
<span class="keyword">from</span> toolbox <span class="keyword">import</span> turn_right <span class="keyword">as</span> nach_rechts

<span class="comment"># Anwendung:</span>
nach_rechts()
turn_off()
</pre>
</li>
</ol>

<p>Das Wort <tt><span class="keyword">as</span></tt> ist ein Python-Schlüsselwort.
    Wir haben erklärt, was mit dieser Anweisung gemeint ist, als
    wir über <i>Variablen</i> sprachen.</p>

<h3 class="section">4. Was machen wir mit langen Modulnamen?</h3>

<p>Wenn du den möglichen Nutzen des Moduls "toolbox" für
deine eigenen Programme in Betracht ziehst ... könntest du
auf die Idee kommen, dass es zu beschränkt ist, um überhaupt
von Nutzen zu sein. Du kannst dir das an folgendem Beispiel
klarmachen:</p>

<pre>
<span class="comment"># Modul importieren</span>
<span class="keyword">import</span> mond_rakete_countdown

<span class="comment"># Anweisungen benutzen (zu lang)</span>
mond_rakete_countdown.start()
mond_rakete_countdown.stop()
</pre>

<p>Glücklicherweise können wir beim Import nicht nur einzelne Namen umbenennen,
sondern auch das ganze Modul:</p>

<pre>
<span class="comment">#  Modul mit Abkuerzung importieren</span>
<span class="keyword">import</span> mond_rakete_countdown <span class="keyword">as</span> countdown

<span class="comment"># Anweisungen benutzen (gut so)</span>
countdown.start()
countdown.stop()
</pre>

<h3 class="section">5. Warum überhaupt importieren?</h3>

<p>Es wird oft gesagt, dass bei Python die <i>Batterien inbegriffen</i> sind.
Sicher haben die meisten schon mal ein elektrisches Spielzeug gekauft und sich
geärgert, dass es nicht funktionierte, weil die Batterien noch fehlten. Ähnlich
ist es bei manchen Programmiersprachen, bei denen man nicht so richtig loslegen
kann, weil man viele grundlegende Funktionen erst selbst programmieren muss. 
Das ist bei Python glücklicherweise nicht so, denn wenn du es installiert hast,
stellt es dir sofort eine umfangreiche <i>Standardbibliothek</i> zur Verfügung. Das
heißt, dass Python mit vielen nützlichen Modulen geliefert wird, die von sehr
klugen und kenntnisreichen Leuten geschrieben wurden. Diese Module sind sehr
effizient programmiert und rigoros auf Fehlerfreiheit getestet. Wenn du mehr
über Python lernst und deine eigenen "komplizierten" Programme schreiben
möchtest, lohnt es sich wirklich, zuerst zu prüfen, ob es ein passendes Modul
in Pythons <i>Standardbibliothek</i> gibt, das dir bei deiner Aufgabe helfen
könnte.</p>

<p>Wichtiger Hinweis für Lehrer: wie bereits oben erwähnt, liegt der Grund für
die Beschränkung der import-Anweisung darin zu vermeiden, dass jemand in den 
Besitz eines bösartigen Moduls gelangt und es an ein ahnungsloses Opfer 
weitergibt. Im Editorfenster von Python kann das immer noch passieren, aber
dann wissen die Studenten hoffentlich genug, um Programme, die sie von 
"Freunden" bekommen haben, zu überprüfen, bevor sie sie ausprobieren. In einer
Klassenraum-Umgebung kann es aber durchaus nützlich sein, in RUR-PLE beliebige
import-Anweisungen zu erlauben. Wenn man mit Python vertraut ist, kann man das
mit einer kleinen Änderung am Quelltext recht einfach bewerkstelligen. Bitte
nimm mit dem Autor Kontakt auf, wenn du dafür einen Bedarf hast und Hilfe
brauchst.</p>

<div class="lessons_nav">
<a href="38-class2.htm"><img alt="previous" src=
"../../images/previous.png" />Ein Hauch von Klasse</a> - <a href=
"../lessons_toc.htm"><img alt="home" src="../../images/home.png" /></a> - <a href=
"40-random.htm">Glücklich entkommen<img alt="next"
src="../../images/next.png" /></a>
</div>
</body>
</html>
